﻿using MikuMikuLibrary.Archives.Farc;
using MikuMikuLibrary.Databases;
using MikuMikuLibrary.Sprites;
using MikuMikuLibrary.Textures;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ft_module_parser.sprutilities
{
    static class sprselpvmerge
    {
        public static SpriteDatabase Make(SpriteDatabase spritedb, Bitmap source, Bitmap source2, Bitmap source3, int id = 0, string farcpath = "")
        {
            Bitmap bm1 = new Bitmap(1024, 512);
            Bitmap bm0 = new Bitmap(2048, 1024);

            if ((source != null) && (source2 != null))
            {
                var canvas = Graphics.FromImage(bm0);
                canvas.CompositingQuality = CompositingQuality.HighQuality;
                canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
                canvas.SmoothingMode = SmoothingMode.HighQuality;
                {
                    canvas.DrawImage(source, 0, 0, 1283, 723);
                }
                {
                    var bmp3 = new Bitmap(504, 504);
                    int width = 504;
                    int height = 504;
                    var canvas2 = Graphics.FromImage(bmp3);

                    // Scaling
                    float scaling;
                    float scalingY = (float)source2.Height / height;
                    float scalingX = (float)source2.Width / width;
                    if (scalingX < scalingY) scaling = scalingX; else scaling = scalingY;

                    int newWidth = (int)(source2.Width / scaling);
                    int newHeight = (int)(source2.Height / scaling);

                    // Correct float to int rounding
                    if (newWidth < width) newWidth = width;
                    if (newHeight < height) newHeight = height;

                    // See if image needs to be cropped
                    int shiftX = 0;
                    int shiftY = 0;

                    if (newWidth > width)
                    {
                        shiftX = (newWidth - width) / 2;
                    }

                    if (newHeight > height)
                    {
                        shiftY = (newHeight - height) / 2;
                    }

                    canvas2.DrawImage(source2, -shiftX, -shiftY, newWidth, newHeight);
                    canvas.DrawImage(bmp3, 1283, 0, 504, 504);
                }

                if (source3 != null)
                {
                    var canvas3 = Graphics.FromImage(bm1);
                    {
                        int height = 512;
                        int width = 1024;
                        // Scaling
                        float scaling;
                        float scalingY = (float)source3.Height / height;
                        float scalingX = (float)source3.Width / width;
                        if (scalingX < scalingY) scaling = scalingX; else scaling = scalingY;

                        int newWidth = (int)(source3.Width / scaling);
                        int newHeight = (int)(source3.Height / scaling);

                        // Correct float to int rounding
                        if (newWidth < width) newWidth = width;
                        if (newHeight < height) newHeight = height;

                        // See if image needs to be cropped
                        int shiftX = 0;
                        int shiftY = 0;

                        if (newWidth > width)
                        {
                            shiftX = (newWidth - width) / 2;
                        }

                        if (newHeight > height)
                        {
                            shiftY = (newHeight - height) / 2;
                        }
                        canvas3.DrawImage(source3, -shiftX, -shiftY, newWidth, newHeight);
                    }
                }

                SpriteSet sprite = new SpriteSet();
                sprite.Load(new MemoryStream(rescb.spr_sel_pv));

                sprite.TextureSet.Textures[0] = TextureEncoder.Encode(bm0, TextureFormat.DXT5, false);
                sprite.TextureSet.Textures[0].Name = "MERGE_D5COMP_0";
                sprite.TextureSet.Textures[1] = TextureEncoder.Encode(bm1, TextureFormat.DXT5, false);
                sprite.TextureSet.Textures[1].Name = "MERGE_D5COMP_1";

                MemoryStream dest0 = new MemoryStream();
                sprite.Save(dest0, true);
                var farc = new FarcArchive();
                farc.Add("spr_sel_pv" + String.Format("{0:000}", id) + ".bin", dest0, false);
                farc.IsCompressed = true;
                farc.Save(farcpath + @"spr_sel_pv" + String.Format("{0:000}", id) + ".farc");
                
                if (spritedb != null)
                {
                    int maxid = 0;
                    try
                    {
                        maxid = spritedb.SpriteSets.Max(c => c.Id);

                        foreach (var sprites in spritedb.SpriteSets)
                        {
                            foreach (var sprite0 in sprites.Sprites)
                                if (maxid < sprite0.Id) maxid = sprite0.Id;

                            foreach (var tex0 in sprites.Textures)
                                if (maxid < tex0.Id) maxid = tex0.Id;
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.ToString());
                    }
                    maxid++;

                    var newsprite = new SpriteSetEntry();
                    newsprite.Name = "SPR_SEL_PV" + String.Format("{0:000}", id);
                    newsprite.FileName = "spr_sel_pv" + String.Format("{0:000}", id) + ".bin";
                    newsprite.Id = maxid;
                    maxid++;
                    var sprentry0 = new SpriteEntry();
                    sprentry0.Id = maxid;
                    sprentry0.Index = 0;
                    sprentry0.Name = "SPR_SEL_PV" + String.Format("{0:000}", id) + "_SONG_BG" + String.Format("{0:000}", id);
                    maxid++;
                    var sprentry1 = new SpriteEntry();
                    sprentry1.Id = maxid;
                    sprentry1.Index = 1;
                    sprentry1.Name = "SPR_SEL_PV" + String.Format("{0:000}", id) + "_SONG_JK" + String.Format("{0:000}", id);
                    maxid++;
                    var sprentry2 = new SpriteEntry();
                    sprentry2.Id = maxid;
                    sprentry2.Index = 2;
                    sprentry2.Name = "SPR_SEL_PV" + String.Format("{0:000}", id) + "_SONG_LOGO" + String.Format("{0:000}", id);
                    maxid++;
                    var texentry0 = new SpriteTextureEntry();
                    texentry0.Id = maxid;
                    texentry0.Index = 0;
                    texentry0.Name = "SPRTEX_SEL_PV" + String.Format("{0:000}", id) + "_MERGE_BC5COMP_0";
                    maxid++;
                    var texentry1 = new SpriteTextureEntry();
                    texentry1.Id = maxid;
                    texentry1.Index = 1;
                    texentry1.Name = "SPRTEX_SEL_PV" + String.Format("{0:000}", id) + "_MERGE_D5COMP_0";

                    newsprite.Sprites.Add(sprentry0);
                    newsprite.Sprites.Add(sprentry1);
                    newsprite.Sprites.Add(sprentry2);
                    newsprite.Textures.Add(texentry0);
                    newsprite.Textures.Add(texentry1);

                    spritedb.SpriteSets.Add(newsprite);
                }
                
            }
            return spritedb;
        }
    }
}
